<!DOCTYPE html>

<html>
<head>
<meta charset="UTF-8">
<link href="style.css" type="text/css" rel="stylesheet">
<title>SYSENTER—Fast System Call </title></head>
<body>
<h1>SYSENTER—Fast System Call</h1>
<table>
<tr>
<th>Opcode</th>
<th>Instruction</th>
<th>Op/En</th>
<th>64-Bit Mode</th>
<th>Compat/Leg Mode</th>
<th>Description</th></tr>
<tr>
<td>0F 34</td>
<td>SYSENTER</td>
<td>NP</td>
<td>Valid</td>
<td>Valid</td>
<td>Fast call to privilege level 0 system procedures.</td></tr></table>
<h3>Instruction Operand Encoding</h3>
<table>
<tr>
<td>Op/En</td>
<td>Operand 1</td>
<td>Operand 2</td>
<td>Operand 3</td>
<td>Operand 4</td></tr>
<tr>
<td>NP</td>
<td>NA</td>
<td>NA</td>
<td>NA</td>
<td>NA</td></tr></table>
<h2>Description</h2>
<p>Executes a fast call to a level 0 system procedure or routine. SYSENTER is a companion instruction to SYSEXIT. The instruction is optimized to provide the maximum performance for system calls from user code running at privilege level 3 to operating system or executive procedures running at privilege level 0.</p>
<p>When executed in IA-32e mode, the SYSENTER instruction transitions the logical processor to 64-bit mode; other-wise, the logical processor remains in protected mode.</p>
<p>Prior to executing the SYSENTER instruction, software must specify the privilege level 0 code segment and code entry point, and the privilege level 0 stack segment and stack pointer by writing values to the following MSRs:</p>
<p>These MSRs can be read from and written to using RDMSR/WRMSR. The WRMSR instruction ensures that the IA32_SYSENTER_EIP and IA32_SYSENTER_ESP MSRs always contain canonical addresses.</p>
<p>While SYSENTER loads the CS and SS selectors with values derived from the IA32_SYSENTER_CS MSR, the CS and SS descriptor caches are <strong>not</strong> loaded from the descriptors (in GDT or LDT) referenced by those selectors. Instead, the descriptor caches are loaded with fixed values. See the Operation section for details. It is the responsibility of OS software to ensure that the descriptors (in GDT or LDT) referenced by those selector values correspond to the fixed values loaded into the descriptor caches; the SYSENTER instruction does not ensure this correspondence.</p>
<p>The SYSENTER instruction can be invoked from all operating modes except real-address mode.</p>
<p>The SYSENTER and SYSEXIT instructions are companion instructions, but they do not constitute a call/return pair. When executing a SYSENTER instruction, the processor does not save state information for the user code (e.g., the instruction pointer), and neither the SYSENTER nor the SYSEXIT instruction supports passing parameters on the stack.</p>
<p>To use the SYSENTER and SYSEXIT instructions as companion instructions for transitions between privilege level 3 code and privilege level 0 operating system procedures, the following conventions must be followed:</p>
<p>The SYSENTER and SYSEXIT instructions were introduced into the IA-32 architecture in the Pentium II processor. The availability of these instructions on a processor is indicated with the SYSENTER/SYSEXIT present (SEP) feature flag returned to the EDX register by the CPUID instruction. An operating system that qualifies the SEP flag must also qualify the processor family and model to ensure that the SYSENTER/SYSEXIT instructions are actually present. For example:</p>
<p>IF CPUID SEP bit is set</p>
<p>THEN IF (Family = 6) and (Model &lt; 3) and (Stepping &lt; 3)</p>
<p>THEN</p>
<p>SYSENTER/SYSEXIT_Not_Supported; FI;</p>
<p>ELSE</p>
<p>SYSENTER/SYSEXIT_Supported; FI;</p>
<p>FI;</p>
<p>When the CPUID instruction is executed on the Pentium Pro processor (model 1), the processor returns a the SEP flag as set, but does not support the SYSENTER/SYSEXIT instructions.</p>
<h2>Operation</h2>
<pre>IF CR0.PE = 0 OR IA32_SYSENTER_CS[15:2] = 0 THEN #GP(0); FI;
RFLAGS.VM ← 0;
                                                    (* Ensures protected mode execution *)
RFLAGS.IF ← 0;
                                                    (* Mask interrupts *)
IF in IA-32e mode
    THEN
         RSP ← IA32_SYSENTER_ESP;
         RIP ← IA32_SYSENTER_EIP;
ELSE
         ESP ← IA32_SYSENTER_ESP[31:0];
         EIP ← IA32_SYSENTER_EIP[31:0];
FI;
CS.Selector ← IA32_SYSENTER_CS[15:0] AND FFFCH;
                                                    (* Operating system provides CS; RPL forced to 0 *)
(* Set rest of CS to a fixed value *)
CS.Base ← 0;
                                                    (* Flat segment *)
CS.Limit ← FFFFFH;
                                                    (* With 4-KByte granularity, implies a 4-GByte limit *)
CS.Type ← 11;
                                                    (* Execute/read code, accessed *)
CS.S ← 1;
CS.DPL ← 0;
CS.P ← 1;
IF in IA-32e mode
    THEN
         CS.L ← 1;
                                                    (* Entry is to 64-bit mode *)
         CS.D ← 0;
                                                    (* Required if CS.L = 1 *)
    ELSE
         CS.L ← 0;
         CS.D ← 1;
                                                    (* 32-bit code segment*)
FI;
CS.G ← 1;
                                                    (* 4-KByte granularity *)
CPL ← 0;
SS.Selector ← CS.Selector + 8;
                                                    (* SS just above CS *)
(* Set rest of SS to a fixed value *)
SS.Base ← 0;
                                                    (* Flat segment *)
SS.Limit ← FFFFFH;
                                                    (* With 4-KByte granularity, implies a 4-GByte limit *)
SS.Type ← 3;
                                                    (* Read/write data, accessed *)
SS.S ← 1;
SS.DPL ← 0;
SS.P ← 1;
SS.B ← 1;
                                                    (* 32-bit stack segment*)
SS.G ← 1;
                                                    (* 4-KByte granularity *)</pre>
<h2>Flags Affected</h2>
<p>VM, IF (see Operation above)</p>
<h2>Protected Mode Exceptions</h2>
<table class="exception-table">
<tr>
<td>#GP(0)</td>
<td>If IA32_SYSENTER_CS[15:2] = 0.</td></tr>
<tr>
<td>#UD</td>
<td>If the LOCK prefix is used.</td></tr></table>
<h2>Real-Address Mode Exceptions</h2>
<table class="exception-table">
<tr>
<td>#GP</td>
<td>The SYSENTER instruction is not recognized in real-address mode.</td></tr>
<tr>
<td>#UD</td>
<td>If the LOCK prefix is used.</td></tr></table>
<h2>Virtual-8086 Mode Exceptions</h2>
<p>Same exceptions as in protected mode.</p>
<h2>Compatibility Mode Exceptions</h2>
<p>Same exceptions as in protected mode.</p>
<h2>64-Bit Mode Exceptions</h2>
<p>Same exceptions as in protected mode.</p></body></html>